import { defaults as defaultControls, FullScreen, ZoomSlider } from 'ol/control'
import { boundingExtent, getBottomLeft, getBottomRight, getTopRight, getTopLeft, containsExtent } from 'ol/extent'
import { defaults as DefaultInteraction } from 'ol/interaction'
import { Tile as TileLayer } from 'ol/layer'
import { getUid } from 'ol/util'
import Polygon from 'ol/geom/Polygon'
import XYZ from 'ol/source/XYZ'
import { OlMap, OlView } from './type'
import LngLat from './WLngLat'
import VectorLayer from './WVectorLayer'

import { calculateCenter, getMapBaseLayerOptions, isFunction, fromLonLat, toLonLat, throttle } from './utils'

//默认参数
const defaultMapOptions = {
	center: [116.397428, 39.90923], //地图中心- 北京
	zoom: 5, //地图缩放层级
	minZoom: 0, // 最小可缩放层级
	maxZoom: 18, // 最大可缩放层级
	doubleClickZoom: false, // 是否双击放大
	zoomShow: true, // 是否显示缩放控件
	zoomSlider: false, // 是否显示滑块缩放控件
	fullScreen: false, // 是否显示全屏控件
	maxExtent: false, // 是否限制地图可拖动范围 - 关联 mouseMoveExtent
	mouseMoveExtent: [
		[10.571664, 0.747024],
		[177.916617, 89.028265]
	], //默认拖动范围范围
	type: 'standard', // 地图底图图层类型
	projection: 'EPSG:3857', // 地图视图投影坐标系
}

//创建底图图层
function createBaseLayers(className = 'standard', visible = true, layerOptions = []) {
	return layerOptions.map(([url = '', projection = 'EPSG:3857']) => {
		return new TileLayer({
			zIndex: 0, // 底图图层层级
			visible, //底图显示隐藏
			className: 'ol-layer ' + className,
			source: new XYZ({
				url,
				projection,
				wrapX: true, // 是否水平包裹世界。
				crossOrigin: 'anonymous' // 图片跨域允许
			})
		})
	})
}

//初始化WMap
function initWMap(target, options) {
	const {
		center, //地图中心
		zoom, //地图缩放层级
		minZoom, // 最小可缩放层级
		maxZoom, // 最大可缩放层级
		doubleClickZoom, // 是否双击放大
		zoomShow, // 是否显示缩放控件
		zoomSlider, // 是否显示滑块缩放控件
		fullScreen, // 是否显示全屏控件
		maxExtent, //限制地图可拖动范围
		mouseMoveExtent,
		projection,
		type
	} = options

	const mapMouseMoveExtent = boundingExtent([fromLonLat(mouseMoveExtent[0]), fromLonLat(mouseMoveExtent[1])])
	//默认控件
	const controlsExtend = [fullScreen ? new FullScreen() : null, zoomSlider ? new ZoomSlider() : null]
	//默认底图图层

	// 标准
	const standardBaseLayers = createBaseLayers(type, true, getMapBaseLayerOptions(type, projection))
	// 卫星
	const satelliteBaseLayers = createBaseLayers('satellite', false, getMapBaseLayerOptions('satellite', projection))

	const mapView = new OlView({
		projection: projection,
		center: fromLonLat(center), // 中心点
		zoom, // 层级
		minZoom, // 最小缩放
		maxZoom, // 最大缩放0
		multiWorld: false, // 控制无法边缘平移
		constrainResolution: true, // 控制缩放为整数
		extent: !maxExtent ? undefined : mapMouseMoveExtent
	})

	// 地图初始化
	return new OlMap({
		target,
		layers: [...standardBaseLayers, ...satelliteBaseLayers], // 图层
		overlays: [], // 覆盖物
		view: mapView,
		interactions: new DefaultInteraction({
			attribution: true,
			doubleClickZoom // 屏蔽默认双击放大事件
		}),
		controls: defaultControls({ zoom: zoomShow }).extend(controlsExtend.filter(c => c))
	})
}

// 地图类
function WMap(target = 'map', options = {}) {
	if (!target || typeof target !== 'string') throw new Error('请传入正确的参数！')

	const assignOptions = Object.assign({}, defaultMapOptions, options)

	const map = initWMap(target, assignOptions) // 继承this属性
	let clickTimeId = null //单击事件定时器

	// 支持的事件
	const events = ['complete', 'moveend', 'click', 'dblclick', 'contextmenu', 'moving', 'pointermove', 'change:size', 'zoom']

	//是否移除 map 点击事件
	let isOffClick = false

	this.WTYPE = 'MAP'

  // this.renderStatus = false // 地图是否渲染完成 用于将事件绑定在地图渲染完成之后

	this.olTarget = map

	this.markerCluster = null // 聚合图层对象

	this.WEvents = new Map() // 存储事件

	this.view = map.getView() // 获取地图的初始化 View 信息

	this.getCenter = () => toLonLat(this.view.getCenter()) // 获取地图的中心位置

	this.getMaxZoom = () => this.view.getMaxZoom() // 获取地图设置的最大放大

	this.getMinZoom = () => this.view.getMinZoom() // 获取地图设置的最小缩放

	this.getResolution = () => this.view.getResolution() // 获取地图分辨率

	this.getRotation = () => this.view.getRotation() // 获取地图旋转

	this.getOverlayById = map.getOverlayById.bind(map) // 根据ID获取覆盖物

	this.getFeatureById = id => this.vectorLayer.getFeatureById(id) // 根据ID获取默认矢量图层对象的 Feature

	this.getLayers = map.getLayers.bind(map) // 获取所有图层

	this.getView = map.getView.bind(map) // 获取 View对象

	this.getViewport = map.getViewport.bind(map) // 获取 Viewport

	this.getSize = map.getSize.bind(map) // 获取 获取可视区域的宽高

	this.getTarget = map.getTarget.bind(map) // 获取 target的值  -- map

	this.updateSize = map.updateSize.bind(map) // 强制更新视口大小

	this.getOverlays = map.getOverlays.bind(map) // 获取所有 OverlayMarkers

	this.getFeaturesAtPixel = map.getFeaturesAtPixel.bind(map) // 从 坐标 获取 Features集合

	this.hasFeatureAtPixel = map.hasFeatureAtPixel.bind(map) // 判断是否点击了 Feature

	this.forEachFeatureAtPixel = map.forEachFeatureAtPixel.bind(map) // 从Features 里面遍历 点Pixel

	this.addControl = map.addControl.bind(map) // 添加控件

	this.removeLayer = map.removeLayer.bind(map) // 移除图层

	this.getCoordinateFromPixel = map.getCoordinateFromPixel.bind(map) // 获取当前点击坐标点

	this.getPixelFromCoordinate = map.getPixelFromCoordinate.bind(map) // 获取当前经纬度坐标像素点

	this.removeOverlay = map.removeOverlay.bind(map) // 移除覆盖物

	this.getKeys = map.getKeys.bind(map)

	this.render = map.render.bind(map) // 渲染执行函数

	this.getEventPixel = map.getEventPixel.bind(map) // 返回浏览器事件相对于视口的地图像素位置。

	this.getTargetElement = map.getTargetElement.bind(map) // 获取地图dom

	this.containsExtent = containsExtent // 一个范围是否包含另外一个范围

	this.getExtent = () => map.getView().calculateExtent(map.getSize()) // 获取地图可视区域 1倍

	this.getExtentBottomLeft = () => toLonLat(getBottomLeft(this.getExtent())) // 获取地图可视区域BottomLeft

	this.getExtentBottomRight = () => toLonLat(getBottomRight(this.getExtent())) // 获取地图可视区域BottomRight

	this.getExtentTopLeft = () => toLonLat(getTopLeft(this.getExtent())) // 获取地图可视区域 TopLeft

	this.getExtentTopRight = () => toLonLat(getTopRight(this.getExtent())) // 获取地图可视区域 TopRight

	this.addOverlay = overlay => overlay && map.addOverlay(overlay) // 添加overlay

  this.dispatchEvent = () => map.dispatchEvent.bind(map) // 事件调度

	// 根据id获取marker
	this.getMarkerById = (id, type = 'VMarker') => {
		if (type === 'VMarker') {
			return map.getOverlayById(id)
		}
	}

	// 获取当前层级
	this.getZoom = function () {
		return this.view.getZoom()
	}

	// 设置当前层级
	this.setZoom = function (zoom) {
		this.view.animate({ zoom, duration: 500 })
	}

	// 获取默认矢量图层
	this.getVectorLayer = () => {
		return this.getLayers()
			.getArray()
			.find(layer => layer.getClassName().indexOf('WMap-vector-layer') !== -1)
	}
	// 获取默认置顶图层
	this.getVectorTopLayer = () => {
		return this.getLayers()
			.getArray()
			.find(layer => layer.getClassName().indexOf('WMap-vector-top-layer') !== -1)
	}

	// 卫星地图图层
	this.getSatelliteLayers = () => {
		return this.getLayers()
			.getArray()
			.filter(layer => layer.getClassName().indexOf('satellite') !== -1)
	}

	// 标准地图图层
	this.getStandardLayers = () => {
		return this.getLayers()
			.getArray()
			.filter(layer => layer.getClassName().indexOf('standard') !== -1)
	}

	// 事件监听
	this.on = (eventName, callBack = () => {}, clickTimeDelay = 0) => {
		if (!eventName || typeof eventName !== 'string') throw new Error('请传入正确的 eventName！')
		if (!events.includes(eventName) && eventName.substring(0, 8) !== 'WMarker' && eventName.substring(0, 9) !== 'WCluster' && eventName.substring(0, 8) !== 'dispatch')
			return console.warn('无效的事件：' + eventName)
		if (callBack && !isFunction(callBack)) throw new Error('请传入正确的 callBack!')
		const eventObject = {
			eventName,
			callBack,
			handler: () => {}
		}

		if (eventObject.eventName === 'complete') {
			//添加 complete 事件 
			this.olTarget.once('rendercomplete', e => callBack(e))
			return
		} else if (eventObject.eventName === 'moveend') {
			//添加 moveend 事件
			eventObject.handler = e => callBack(e)
		} else if (eventObject.eventName === 'pointermove') {
			eventObject.handler = e => callBack(e)
		} else if (eventObject.eventName === 'change:size') {
			eventObject.handler = e => callBack(e)
		}else if (eventObject.eventName === 'zoom') {
      // 内置监听地图层级变化
      // this.view.on('change:resolution', throttle((e) => {
      //   return callBack(e.target)
      // }))
      return this.olTarget.on('moveend', e => callBack({
        target: e.target,
        zoom :e.target.getView().getZoom()
      }))
    } else if (eventObject.eventName.substring(0, 8) === 'dispatch') {
      // 自定义事件派发
      eventObject.handler = e => callBack(e)
    } else {
			const eventHandler = (e, olMap, eventObject) => {
				clickTimeId && clearTimeout(clickTimeId)
				clickTimeId = setTimeout(() => {
					if (olMap.hasFeatureAtPixel(e.pixel)) {
						// 获取点击的图层，以及要素
						const [olFeature, olLayer] = olMap.forEachFeatureAtPixel(e.pixel, (feature, layer) => [feature, layer])
						const WEvents = olFeature.get('WEvents') || new Map()

						const dispatchAction = (target, eventTarget, WEvents, event) => {
							const id = target.get('id') || getUid(target) // 聚合物散开的 feature 存在 ol_uid 但是不与其id相同
							WEvents.forEach(function (currentEventObject, eventName) {
								if (eventName.indexOf(id) !== -1 && /\((.+)\)/.exec(eventName)[1] === e.type) {
									target.dispatchEvent({
										type: eventName, // 订阅事件对象的名称
										callBack: currentEventObject.callBack, // 订阅事件对象的回调
										eventName: event.type, // 实际派发的事件
										event, // 触发的事件的鼠标事件
										eventTarget // 实际应该接收事件ol 对象
									})
								}
							})
						}

						if (olFeature.WTYPE === 'ClusterMarker') {
							//聚合要素 features
							const features = olFeature.get('features')

							if (features.length === 1) {
								// 存在单个feature
								if (!WEvents.size) {
									//执行地图事件
									!isOffClick && eventObject.callBack(e)
								} else {
									// 派发事件
									// WEvents 存在于 features[0] 中
									// const WEvents = features[0].get('WEvents') || new Map()
									dispatchAction(features[0], features[0], WEvents, e)
								}
							} else {
								//聚合物对象
								const WEvents = olLayer.get('WEvents') || new Map()
								// 散开聚合物
								if (this.getMarkerClusterer().options.zoomOnClick) {
									this.getMarkerClusterer().setClusterExtentView(olFeature)
								}

								if (!WEvents.size) {
									//执行地图事件
									!isOffClick && eventObject.callBack(e)
								} else {
									// 派发事件
									dispatchAction(olLayer, olFeature, WEvents, e)
								}
							}
						} else if (!olFeature.WTYPE && olFeature.get('WTYPE') === 'OlDraw') {
							// dispatchAction(olFeature, olFeature, WEvents, e)
							// 这里暂时不做处理 特殊实例：主动绘制完图形点击事件，目前可不加
						} else {
							// console.log(WEvents)
							// 非聚合要素features
							if (!WEvents.size) {
								//执行地图事件
								!isOffClick && eventObject.callBack(e)
							} else {
								// 派发事件
								dispatchAction(olFeature, olFeature, WEvents, e)
							}
						}
					} else if (e.type === eventObject.eventName) {
						//点击其他地方处理
						!isOffClick && eventObject.callBack(e)
					}
				}, eventObject.delay)
			}

			eventObject.delay = clickTimeDelay || 200

			eventObject.handler = e => {
				e.lngLat = new LngLat(toLonLat(e.coordinate))
				eventHandler(e, map, eventObject)
			}

			isOffClick = false
		}

		// 未绑定过事件
		if (!this.WEvents.has(eventObject.eventName)) {
			//事件监听
			this.olTarget.on(eventObject.eventName, eventObject.handler)

			//储存事件
			this.WEvents.set(eventObject.eventName, eventObject)
		} else {
			const currentEventObject = this.WEvents.get(eventObject.eventName)

			// 移除事件
			this.olTarget.un(currentEventObject.eventName, currentEventObject.handler)

			// 重新设置监听事件
			this.olTarget.on(currentEventObject.eventName, eventObject.handler)

			//储存新事件
			this.WEvents.set(currentEventObject.eventName, eventObject)
		}
		this.olTarget.set('WEvents', this.WEvents)
	}

	// 注销事件监听
	this.off = eventName => {
		if (this.WEvents.has(eventName)) {
			// 获取事件对象
			const currentEventObject = this.WEvents.get(eventName)

			// 移除事件
			this.olTarget.un(currentEventObject.eventName, currentEventObject.handler)

			// 删除事件存储
			this.WEvents.delete(eventName)

			this.olTarget.set('WEvents', this.WEvents)
		}
	}

	// 切换地图类型
	this.setBaseLayer = layerName => {
		if (layerName === 'satellite') {
			this.getStandardLayers().forEach(layer => layer.setVisible(false))
			this.getSatelliteLayers().forEach(layer => layer.setVisible(true))
		} else if (layerName === 'standard') {
			this.getSatelliteLayers().forEach(layer => layer.setVisible(false))
			this.getStandardLayers().forEach(layer => layer.setVisible(true))
		} else {
			this.getSatelliteLayers().forEach(layer => layer.setVisible(false))
			!this.getStandardLayers()[0].getVisible() && this.getStandardLayers().forEach(layer => layer.setVisible(true))
		}
	}

	// 添加图层
	this.addLayer = layer => {
		// WMap-clusterer-layer 聚合图层
		map.addLayer(layer)
	} // 添加图层

	// 获取聚合图层
	this.getMarkerClusterer = () => {
		return this.markerCluster
	}

	// 设置聚合图层
	this.setMarkerClusterer = markerCluster => {
		if (!markerCluster || markerCluster.WTYPE !== 'MARKERCLUSTER') return
		this.markerCluster = markerCluster
	}

	// 设置置顶 - 特殊情况，存在bug:聚合要素置顶切换，旧的置顶可能会被添加到聚合里面瞿
	this.setTop = (() => {
		let cache = {
			olTarget: null,
			layer: null,
			isClustererfeature: false
		}
		return target => {
			const olTarget = target.olTarget ? target.olTarget : target
			const topTarget = this.vectorTopLayer.getFeatures()[0]
			const markerClusterer = this.getMarkerClusterer()
			const isClustererfeature = !markerClusterer ? false : markerClusterer?.getClusterSource().singleFeatureIds.has(olTarget.getId()) // 是否在聚合对象内
			// console.log(isClustererfeature, markerClusterer?.getClusterSource().singleFeatureIds.size)

			if (isClustererfeature) {
				cache.isClustererfeature = true
				// 置顶 feature 在聚合内
				if (!topTarget) {
					markerClusterer.remove(olTarget)
					this.vectorTopLayer.add(olTarget)
					cache.olTarget = olTarget
					cache.layer = markerClusterer
				} else {
					if (olTarget !== topTarget) {
						markerClusterer.remove(olTarget) // 移除 本次置顶要素
						if (markerClusterer === cache.layer) {
							this.vectorTopLayer.remove(cache.olTarget)
							markerClusterer.add(topTarget)
							this.vectorTopLayer.add(olTarget)
							cache.olTarget = olTarget
							cache.layer = markerClusterer
						} else {
							this.vectorTopLayer.remove(topTarget) // 移除 上次置顶要素
							this.vectorTopLayer.add(olTarget) // 添加 本次置顶要素
							cache.layer.add(cache.olTarget) // 还原 上次置顶要素
							cache.olTarget = olTarget
							cache.layer = markerClusterer
						}
					}
				}
			} else {
				// 非聚合feature
				if (!topTarget) {
					this.vectorLayer.remove(olTarget)
					this.vectorTopLayer.add(olTarget)
					cache.olTarget = olTarget
					cache.layer = this.vectorLayer
				} else {
					if (olTarget !== topTarget) {
						if (cache.isClustererfeature) {
							this.vectorTopLayer.remove(topTarget)
							this.vectorLayer.remove(olTarget)
							this.vectorTopLayer.add(olTarget)
							cache.layer.add(topTarget)
							cache.olTarget = olTarget
							cache.layer = this.vectorLayer
							cache.isClustererfeature = false
						} else {
							this.vectorLayer.remove(olTarget)
							this.vectorTopLayer.remove(topTarget)
							this.vectorTopLayer.add(olTarget)
							this.vectorLayer.add(topTarget)
							cache.olTarget = olTarget
							cache.layer = this.vectorLayer
						}
					}
				}
			}
		}
	})()

	/**
	 * 添加 单个或者多个  覆盖物
	 * @param {*} markers
	 */
	this.add = (...args) => {
		if (args.length === 1) {
			const target = args[0]
			const vectorLayer = this.getVectorLayer()
			const WTYPE = target.WTYPE ? target.WTYPE : 'unknown'
			const targetSwitch = {
        OlOverlay: () => {
          this.addOverlay(target)
        },
				FEATUREMARKER: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
				},
				OVERLAYMARKER: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
					this.addOverlay(target.getOverlayMarker())
				},
				VMarker: () => {
					this.addOverlay(target)
				},
				POLYLINE: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
				},
				// 信息框
				INFOWINDOW: () => {
					this.addOverlay(target.olTarget)
				},
				// 右键菜单栏
				ContextMenu: () => {
					this.addOverlay(target.olTarget)
				},
				// 点 矢量图
				Point: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
					let source = vectorLayer.getSource().getFeatures()
					target.olTarget.set('map', this.olTarget)
					target.olTarget.set('source', source)
				},
				// 线 矢量图
				Line: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
					let source = vectorLayer.getSource().getFeatures()
					target.olTarget.set('map', this.olTarget)
					target.olTarget.set('source', source)
				},
				// 圆形 矢量图
				Circle: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
					let source = vectorLayer.getSource().getFeatures()
					target.olTarget.set('map', this.olTarget)
					target.olTarget.set('source', source)
				},
				// 多边形 矢量图
				Polygon: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
					let source = vectorLayer.getSource().getFeatures()
					target.olTarget.set('map', this.olTarget)
					target.olTarget.set('source', source)
				},
				// 矩形 矢量图
				Rectangle: () => {
					vectorLayer.getSource().addFeature(target.olTarget)
					let source = vectorLayer.getSource().getFeatures()
					target.olTarget.set('map', this.olTarget)
					target.olTarget.set('source', source)
				},
				unknown: () => {
          console.warn(`目前添加的是未知类型覆盖物：${JSON.parse(JSON.stringify(target))}，请修改！`)
          return
        }
			}
			Array.isArray(target) ? this.add(...target) : targetSwitch[WTYPE]()
		} else {
			args.forEach(marker => this.add(marker))
		}
	}

	// map 删除 覆盖物
	this.remove = (...args) => {
		if (args.length === 1) {
			// 单参数或者数组
			const target = args[0]
			if (!target) return target
			if (Array.isArray(target)) {
				target.forEach(marker => this.remove(marker))
			} else {
				const removeFeatureCallBack = (target, callBack) => {
					const olTarget = target.olTarget ? target.olTarget : target
          const activeTarget = target.activeTarget
					const vectorLayerSource = this.getVectorLayer().getSource()
					const VectorTopLayerSource = this.getVectorTopLayer().getSource()
          // 特例：轨迹线中的实时轨迹
          if (activeTarget && vectorLayerSource.hasFeature(activeTarget)) {
            vectorLayerSource.removeFeature(activeTarget)
          }
          // 常规
          if (olTarget) {
            // 主动绘制图形的删除
            if (olTarget.feature)  {
              vectorLayerSource.removeFeature(olTarget.feature)
							callBack && callBack()
            // 普通图层常规删除
            } else if (vectorLayerSource.hasFeature(olTarget)) {
							vectorLayerSource.removeFeature(olTarget)
							callBack && callBack()
            // 顶级图层的常规删除
						} else if (VectorTopLayerSource.hasFeature(olTarget)) {
							VectorTopLayerSource.removeFeature(olTarget)
							callBack && callBack()
						}
					}
				}
				const targetSwitch = {
          // 处理聚合物，change 添加到map 上的 VMarker,
					VMarker: () => map.removeOverlay(target),
					OVERLAYMARKER: () => removeFeatureCallBack(target, () => map.removeOverlay(target.getOverlayMarker())),
					FEATUREMARKER: () => removeFeatureCallBack(target),
					POLYLINE: () => removeFeatureCallBack(target),
					Point: () => removeFeatureCallBack(target),
					Line: () => removeFeatureCallBack(target),
					Circle: () => removeFeatureCallBack(target),
					Polygon: () => removeFeatureCallBack(target),
					Rectangle: () => removeFeatureCallBack(target),
					OlFeature: () => removeFeatureCallBack(target),
          OlDraw: () => removeFeatureCallBack(target),
					unknown: () => {
            console.warn('未知覆盖物，请确认是否传值正确！')
          }
				}
				const WTYPE = target.WTYPE ? target.WTYPE : target.get('WTYPE') ? target.get('WTYPE') : 'unknown'
				targetSwitch[WTYPE]()
			}
		} else {
			// 多个参数
			args.forEach(marker => this.remove(marker))
		}
	}
	/**
	 * 清除地图上各种类型的覆盖物
	 */
	this.clear = () => {
		this.getVectorLayer().getSource().clear() // 清除地图上所有feature
		this.removeGraph() // 清除地图上所有矢量图形交互
		map.getOverlays().clear() // 清除地图上所有overlay覆盖物
		this.getMarkerClusterer()?.clearMarkers() // 清除聚合下的所有覆盖物
	}

	/**
	 * 判断是否有此图层, 并返回
	 * @param {*} layer
	 * @returns
	 */
	this.getLayer = layerName => {
		return map
			.getLayers()
			.getArray()
			.find(layer => layer.getClassName().indexOf(layerName) !== -1)
	}
	/**
	 * 计算覆盖物中心点
	 * @param {*} features
	 * @returns
	 */
	this.calculateCenter = features => calculateCenter(features)

	// 设置地图中心
	this.setCenter = function (coord, zoom = 0, callBack = () => {}) {
		const center = fromLonLat(coord) || (this.getCenter() ? this.getCenter() : [0, 0])
		zoom = zoom || this.getZoom()
		this.view.animate({ zoom, center, duration: 500 }, () => {
			callBack && callBack()
		})
	}

	// 定位到目标位置
	this.panTo = function (coord, options) {
		const mapZoom = this.getZoom()
		const { zoom = mapZoom, duration = 400 } = options || {}
		this.view.animate({
			// 只设置需要的属性即可
			center: fromLonLat(coord), // 中心点
			zoom, // 缩放级别
			duration // 缩放持续时间，默认不需要设置
		})
	}

	/**
	 * 让地图自动适应覆盖
	 * 获取覆盖物群里的 总的最小经纬度和最大经纬度，以此来生成矩形框，然后视图调用fit()方法来适应层级
	 * @param {*} overlay
	 */
	this.setFitView = () => {
		const vectorGraph = this.getLayer('WMap-vector-layer') // 判断是否有矢量图层
		const clusterLayer = this.getLayer('WMap-clusterer-layer') // 判断是否有聚合图层
		const rectangleBox = {
			minLng: Infinity,
			minLat: Infinity,
			maxLng: -Infinity,
			maxLat: -Infinity
		}
		let vectorGraphFeatures = !!vectorGraph ? vectorGraph.getSource().getFeatures() : []
		let clusterLayerFeatures = !!clusterLayer ? clusterLayer.getSource().getSource().getFeatures() : []

		if (vectorGraphFeatures.length > 0) {
			vectorGraphFeatures.forEach(item => {
				//   getExtent 获取左上角 和 右上角坐标方法 分别代表最小经纬和最大经纬
				if (rectangleBox.minLng > item.getGeometry().getExtent()[0]) {
					rectangleBox.minLng = item.getGeometry().getExtent()[0]
				}
				if (rectangleBox.minLat > item.getGeometry().getExtent()[1]) {
					rectangleBox.minLat = item.getGeometry().getExtent()[1]
				}
				if (rectangleBox.maxLng < item.getGeometry().getExtent()[2]) {
					rectangleBox.maxLng = item.getGeometry().getExtent()[2]
				}
				if (rectangleBox.maxLat < item.getGeometry().getExtent()[3]) {
					rectangleBox.maxLat = item.getGeometry().getExtent()[3]
				}
			})
		}

		if (clusterLayerFeatures.length > 0) {
			this.getMarkerClusterer()
				.getMarkers()
				.forEach(item => {
					let flag = item.get('position')
					if (rectangleBox.minLng > flag.olng) {
						rectangleBox.minLng = flag.olng
					}
					if (rectangleBox.minLat > flag.olat) {
						rectangleBox.minLat = flag.olat
					}
					if (rectangleBox.maxLng < flag.olng) {
						rectangleBox.maxLng = flag.olng
					}
					if (rectangleBox.maxLat < flag.olat) {
						rectangleBox.maxLat = flag.olat
					}
				})
		}

		const p1 = rectangleBox.minLng
		const p2 = rectangleBox.minLat
		const p3 = rectangleBox.maxLng
		const p4 = rectangleBox.maxLat

		const polygon = new Polygon([
			[
				[p1, p2],
				[p3, p2],
				[p3, p4],
				[p1, p4],
				[p1, p2]
			]
		])

		if (vectorGraphFeatures.length > 0 || clusterLayerFeatures.length > 0) {
			map.getView().fit(polygon, { padding: [5, 5, 5, 5] })
		}
	}

	// 地图缩小
	this.setZoomOut = function (zoomNum = 1) {
		// 获取地图当前缩放等级
		const zoom = this.getZoom()
		// 每单击一次地图的缩放等级减一，以实现地图缩小
		this.setZoom(zoom - zoomNum)
	}

	// 地图放大
	this.setZoomIn = function (zoomNum = 1) {
		// 获取地图当前缩放等级
		const zoom = this.getZoom()
		// 每单击一次地图的缩放等级减一，以实现地图缩小
		this.setZoom(zoom + zoomNum)
	}

	//获取当前屏幕的 extent
	this.getPointExtent = function (n) {
		n = n ? n : 1
		let mapsize = this.getSize().map(it_ => it_ * n)
		return this.view.calculateExtent(mapsize)
	}

	// 删除 矢量交互图
	this.removeGraph = function (draw) {
		map.removeInteraction(draw)
	}

	this.getInteractions = () => {
		return map.getInteractions()
	}

	// 添加 矢量交互图
	this.addGraph = function (draw) {
		map.addInteraction(draw)
	}

	/**
	 * 默认事件
	 */
	this.defaultEvents = () => {
		if (this.olTarget) {
			this.on(
				'pointermove',
				e => {
					let pixel = this.olTarget.getEventPixel(e.originalEvent)
					let feature = this.olTarget.forEachFeatureAtPixel(pixel, function (feature) {
						return feature
					})
					if (!feature) {
						this.olTarget.getTargetElement().style.cursor = 'auto'
					} else {
						this.olTarget.getTargetElement().style.cursor = 'pointer'
					}
				},
				0
			)
			this.on('click')
			this.on('dblclick')
			this.on('contextmenu')
		}
	}

	this.defaultEvents() // 默认事件添加

	// 默认的矢量图层
	this.vectorLayer = new VectorLayer({ map: this, className: 'WMap-vector-layer' })

	// 置顶图层
	this.vectorTopLayer = new VectorLayer({ map: this, className: 'WMap-vector-top-layer', style: { zIndex: 100 } })
}
export default WMap
